package com.huawei.hms.framework.network.restclient.hwhttp.cronet;

import android.text.TextUtils;
import com.huawei.hms.framework.common.CheckParamUtils;
import com.huawei.hms.framework.common.Logger;
import com.huawei.hms.framework.common.StringUtils;
import com.huawei.hms.framework.network.restclient.Headers;
import com.huawei.hms.framework.network.restclient.Version;
import com.huawei.hms.framework.network.restclient.hianalytics.RCEventListener;
import com.huawei.hms.framework.network.restclient.hianalytics.RequestFinishedInfo;
import com.huawei.hms.framework.network.restclient.hwhttp.HttpContants;
import com.huawei.hms.framework.network.restclient.hwhttp.MediaType;
import com.huawei.hms.framework.network.restclient.hwhttp.Request;
import com.huawei.hms.framework.network.restclient.hwhttp.RequestTask;
import com.huawei.hms.framework.network.restclient.hwhttp.Response;
import com.huawei.hms.framework.network.restclient.hwhttp.ResponseBody;
import com.huawei.hms.framework.network.restclient.hwhttp.model.ConnectionInfo;
import com.huawei.hms.framework.network.restclient.hwhttp.trans.CronetUploadDataProvider;
import com.huawei.hms.framework.network.util.ContextUtil;
import com.huawei.hwid.core.constants.HwAccountConstants;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.chromium.net.CronetEngine;
import org.chromium.net.CronetException;
import org.chromium.net.ExperimentalUrlRequest.Builder;
import org.chromium.net.UploadDataProvider;
import org.chromium.net.UploadDataProviders;
import org.chromium.net.UrlRequest;
import org.chromium.net.UrlRequest.Callback;
import org.chromium.net.UrlResponseInfo;

public class CronetRequestTask implements RequestTask {
    private static final String CONTENT_LENGTH = "Content-Length";
    private static final String TAG = CronetRequestTask.class.getSimpleName();
    private volatile boolean canceled;
    private int chunkLength = -1;
    private boolean connected;
    private final CronetEngine cronetEngine;
    private boolean executed;
    private final CronetRequestTaskFactory factory;
    private IOException mException;
    private boolean mHasResponseHeadersOrCompleted;
    private CronetInputStream mInputStream;
    private boolean mOnRedirectCalled;
    private UrlResponseInfo mResponseInfo;
    private final MessageLoop messageLoop;
    private RCEventListener rcEventListener;
    private Request request;
    private RequestFinishedInfo requestFinishedInfo;
    private UrlRequest urlRequest;

    class CronetUrlRequestCallback extends Callback {
        public void onResponseStarted(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo) {
            CronetRequestTask.this.mResponseInfo = urlResponseInfo;
            CronetRequestTask.this.mHasResponseHeadersOrCompleted = true;
            CronetRequestTask.this.messageLoop.quit();
        }

        public void onReadCompleted(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, ByteBuffer byteBuffer) {
            CronetRequestTask.this.mResponseInfo = urlResponseInfo;
            CronetRequestTask.this.messageLoop.quit();
        }

        public void onRedirectReceived(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, String str) {
            CronetRequestTask.this.mOnRedirectCalled = true;
            try {
                if (new URL(str).getProtocol().equals(CronetRequestTask.this.getProtocol())) {
                    CronetRequestTask.this.urlRequest.followRedirect();
                    return;
                }
            } catch (MalformedURLException e) {
                Logger.v(CronetRequestTask.TAG, "onRedirectReceived occur exception:" + e.getClass().getSimpleName());
            }
            CronetRequestTask.this.mResponseInfo = urlResponseInfo;
            CronetRequestTask.this.urlRequest.cancel();
            setResponseDataCompleted(null);
        }

        public void onSucceeded(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo) {
            CronetRequestTask.this.mResponseInfo = urlResponseInfo;
            setResponseDataCompleted(null);
        }

        public void onFailed(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, CronetException cronetException) {
            if (cronetException == null) {
                throw new IllegalStateException("Exception cannot be null in onFailed.");
            }
            CronetRequestTask.this.mResponseInfo = urlResponseInfo;
            setResponseDataCompleted(cronetException);
        }

        public void onCanceled(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo) {
            CronetRequestTask.this.mResponseInfo = urlResponseInfo;
            setResponseDataCompleted(new IOException("disconnect() called"));
        }

        private void setResponseDataCompleted(IOException iOException) {
            CronetRequestTask.this.mException = iOException;
            if (CronetRequestTask.this.mInputStream != null) {
                CronetRequestTask.this.mInputStream.setResponseDataCompleted(iOException);
            }
            CronetRequestTask.this.mHasResponseHeadersOrCompleted = true;
            CronetRequestTask.this.messageLoop.quit();
        }
    }

    public CronetRequestTask(CronetEngine cronetEngine, CronetRequestTaskFactory cronetRequestTaskFactory) {
        this.cronetEngine = cronetEngine;
        this.messageLoop = new MessageLoop();
        this.factory = cronetRequestTaskFactory;
        this.mInputStream = new CronetInputStream(this);
        this.requestFinishedInfo = new CronetRequestFinishedInfo();
    }

    public void setRcEventListener(RCEventListener rCEventListener) {
        this.rcEventListener = rCEventListener;
    }

    void onRequestFinish() {
        Logger.v(TAG, "onRequestFinish");
        if (this.rcEventListener != null) {
            Logger.v(TAG, "callback rcEventListener#callFinishAtNetLib");
            this.rcEventListener.callFinishAtNetLib();
        }
    }

    public RequestFinishedInfo getRequestFinishedInfo() {
        return this.requestFinishedInfo;
    }

    public Request request() {
        return this.request;
    }

    public Response execute(Request request) throws IOException {
        CheckParamUtils.checkNotNull(request, "request == null");
        Logger.i(TAG, "the request has used the cronet!");
        synchronized (this) {
            if (this.executed) {
                throw new IllegalStateException("Already executed");
            }
            this.executed = true;
        }
        this.request = request;
        if (this.canceled) {
            throw new IOException("Canceled");
        }
        startRequest();
        if (!this.canceled) {
            return parseResponse();
        }
        disconnect();
        throw new IOException("Canceled");
    }

    public void cancel() {
        this.canceled = true;
    }

    public boolean isExecuted() {
        return this.executed;
    }

    public boolean isCanceled() {
        return this.canceled;
    }

    public ConnectionInfo getConnectionInfo() {
        return null;
    }

    public RequestTask clone() {
        return new CronetRequestTask(this.cronetEngine, this.factory);
    }

    public void disconnect() {
        if (this.connected) {
            this.urlRequest.cancel();
        }
    }

    public InputStream getInputStream() throws IOException {
        getResponse();
        if ("HEAD".equalsIgnoreCase(this.request.getMethod())) {
            this.urlRequest.cancel();
        }
        return this.mInputStream;
    }

    private void startRequest() throws IOException {
        if (!this.connected) {
            String str;
            if (this.request.getUrl() == null) {
                str = "";
            } else {
                str = this.request.getUrl().getUrl();
            }
            Builder builder = (Builder) this.cronetEngine.newUrlRequestBuilder(str, new CronetUrlRequestCallback(), this.messageLoop);
            builder.addRequestAnnotation(this);
            String method = this.request.getMethod();
            addPropertiesHeaders(builder, this.request.getHeaders());
            if (this.request.getBody() != null) {
                UploadDataProvider cronetUploadDataProvider;
                if (method.equals(HttpContants.HTTP_METHOD_GET)) {
                    method = "POST";
                }
                if (this.request.getBody().body().length == 0) {
                    if (TextUtils.isEmpty(getRequestProperty(CONTENT_LENGTH))) {
                        addRequestProperty(builder, CONTENT_LENGTH, this.request.getBody().contentLength() + "");
                    }
                    Logger.i(TAG, "using cronet to request" + this.request.getBody().contentLength());
                    cronetUploadDataProvider = new CronetUploadDataProvider(this.request.getBody());
                } else {
                    cronetUploadDataProvider = UploadDataProviders.create(this.request.getBody().body());
                }
                builder.setUploadDataProvider(cronetUploadDataProvider, this.messageLoop);
                addRequestProperty(builder, HttpContants.KEY_CONTENT_TYPE, this.request.getBody().contentType());
                if (TextUtils.isEmpty(getRequestProperty(CONTENT_LENGTH))) {
                    addRequestProperty(builder, CONTENT_LENGTH, "" + cronetUploadDataProvider.getLength());
                }
            }
            builder.setHttpMethod(method);
            this.urlRequest = builder.build();
            this.urlRequest.start();
            this.connected = true;
        }
    }

    private String getRequestProperty(String str) {
        return this.request.getHeaders().get(str);
    }

    private void addPropertiesHeaders(UrlRequest.Builder builder, Headers headers) {
        int i = 0;
        if (builder != null && headers != null) {
            int i2 = 0;
            while (i < headers.size()) {
                String name = headers.name(i);
                builder.addHeader(name, headers.value(i));
                if (i2 == 0 && StringUtils.toLowerCase(name).equals("user-agent")) {
                    i2 = 1;
                }
                i++;
            }
            if (i2 == 0) {
                builder.addHeader("User-Agent", Version.getUserAgent(ContextUtil.getContext()));
            }
        }
    }

    private void addRequestProperty(UrlRequest.Builder builder, String str, String str2) {
        if (str2 != null) {
            builder.addHeader(str, str2);
        }
    }

    public InputStream getErrorStream() {
        try {
            getResponse();
            if (this.mResponseInfo.getHttpStatusCode() >= 400) {
                return this.mInputStream;
            }
            return null;
        } catch (IOException e) {
            return null;
        }
    }

    private int getReadTimeout() {
        return this.request.getReadTimeout() == Request.DEFAULT_NUM ? this.factory.getReadTimeout() : this.request.getReadTimeout();
    }

    public void setConnectTimeout(int i) {
    }

    void getMoreData(ByteBuffer byteBuffer) throws IOException {
        this.urlRequest.read(byteBuffer);
        this.messageLoop.loop(getReadTimeout());
    }

    private String getProtocol() {
        try {
            return this.request.getUrl().getURL().getProtocol();
        } catch (MalformedURLException e) {
            Logger.v(TAG, "getProtocol failed, Exception:%s", e.getClass().getSimpleName());
            return "";
        }
    }

    final String getHeaderField(String str) {
        try {
            getResponse();
            Map allHeaders = getAllHeaders();
            if (!allHeaders.containsKey(str)) {
                return null;
            }
            List list = (List) allHeaders.get(str);
            return (String) list.get(list.size() - 1);
        } catch (IOException e) {
            return null;
        }
    }

    long getHeaderFieldLong(String str, long j) {
        try {
            j = Long.parseLong(getHeaderField(str));
        } catch (NumberFormatException e) {
            Logger.w(TAG, "getHeaderFieldLong failed, Exception:%s", e.getClass().getSimpleName());
        }
        return j;
    }

    private long getContentLength() {
        long headerFieldLong = getHeaderFieldLong("content-length", -1);
        if (headerFieldLong > 2147483647L) {
            return -1;
        }
        return (long) ((int) headerFieldLong);
    }

    private String getContentType() {
        return getHeaderField("content-type");
    }

    private String getContentEncoding() {
        return getHeaderField("content-encoding");
    }

    private Headers parseRespHeaders(Map<String, List<String>> map) {
        Headers.Builder builder = new Headers.Builder();
        Logger.v(TAG, "get response header from server:");
        for (Entry entry : map.entrySet()) {
            for (String add : (List) entry.getValue()) {
                builder.add(TextUtils.isEmpty((CharSequence) entry.getKey()) ? HwAccountConstants.NULL : (String) entry.getKey(), add);
                Logger.v(TAG, "key:%s, value:%s", entry.getKey(), add);
            }
        }
        return builder.build();
    }

    private Response parseResponse() throws IOException {
        getResponse();
        int httpStatusCode = this.mResponseInfo.getHttpStatusCode();
        if (this.canceled) {
            disconnect();
            throw new IOException("Canceled");
        }
        Charset charset;
        Response.Builder builder = new Response.Builder();
        Headers parseRespHeaders = parseRespHeaders(this.mResponseInfo.getAllHeaders());
        ResponseBody.Builder builder2 = new ResponseBody.Builder();
        String contentType = getContentType();
        MediaType parse = contentType != null ? MediaType.parse(contentType) : null;
        ResponseBody.Builder contentType2 = builder2.inputStream(httpStatusCode >= 400 ? getErrorStream() : getInputStream()).contentLength(getContentLength()).contentType(contentType);
        if (parse != null) {
            charset = parse.charset();
        } else {
            charset = null;
        }
        contentType2.charSet(charset);
        builder.code(httpStatusCode).message(this.mResponseInfo.getHttpStatusText()).headers(parseRespHeaders).body(builder2.build());
        if (!this.canceled) {
            return builder.build();
        }
        disconnect();
        throw new IOException("Canceled");
    }

    private void getResponse() throws IOException {
        if (!this.mHasResponseHeadersOrCompleted) {
            startRequest();
            this.messageLoop.loop();
        }
        checkHasResponseHeaders();
    }

    private void checkHasResponseHeaders() throws IOException {
        if (!this.mHasResponseHeadersOrCompleted) {
            throw new IllegalStateException("No response.");
        } else if (this.mException != null) {
            throw this.mException;
        } else if (this.mResponseInfo == null) {
            throw new NullPointerException("Response info is null when there is no exception.");
        }
    }

    private boolean isChunkedUpload() {
        return this.chunkLength > 0;
    }

    private Map<String, List<String>> getAllHeaders() {
        return this.mResponseInfo.getAllHeaders();
    }

    private List<Entry<String, String>> getAllHeadersAsList() {
        return this.mResponseInfo.getAllHeadersAsList();
    }
}
